﻿namespace Community.CsharpSqlite.Entity
{
    /*
    ** CAPI3REF: Memory Allocation Routines
    ** EXPERIMENTAL
    **
    ** An instance of this object defines the interface between SQLite
    ** and low-level memory allocation routines.
    **
    ** This object is used in only one place in the SQLite interface.
    ** A pointer to an instance of this object is the argument to
    ** [ConfigHelper.Sqlite3Config()] when the configuration option is
    ** [ConfigOption.SQLITE_CONFIG_MALLOC] or [ConfigOption.SQLITE_CONFIG_GETMALLOC].  
    ** By creating an instance of this object
    ** and passing it to [ConfigHelper.Sqlite3Config]([ConfigOption.SQLITE_CONFIG_MALLOC])
    ** during configuration, an application can specify an alternative
    ** memory allocation subsystem for SQLite to use for all of its
    ** dynamic memory needs.
    **
    ** Note that SQLite comes with several [built-in memory allocators]
    ** that are perfectly adequate for the overwhelming majority of applications
    ** and that this object is only useful to a tiny minority of applications
    ** with specialized memory allocation requirements.  This object is
    ** also used during testing of SQLite in order to specify an alternative
    ** memory allocator that simulates memory out-of-memory conditions in
    ** order to verify that SQLite recovers gracefully from such
    ** conditions.
    **
    ** The xMalloc and xFree methods must work like the
    ** malloc() and free() functions from the standard C library.
    ** The xRealloc method must work like realloc() from the standard C library
    ** with the exception that if the second argument to xRealloc is zero,
    ** xRealloc must be a no-op - it must not perform any allocation or
    ** deallocation.  ^SQLite guarantees that the second argument to
    ** xRealloc is always a value returned by a prior call to xRoundup.
    ** And so in cases where xRoundup always returns a positive number,
    ** xRealloc can perform exactly as the standard library realloc() and
    ** still be in compliance with this specification.
    **
    ** xSize should return the allocated size of a memory allocation
    ** previously obtained from xMalloc or xRealloc.  The allocated size
    ** is always at least as big as the requested size but may be larger.
    **
    ** The xRoundup method returns what would be the allocated size of
    ** a memory allocation given a particular requested size.  Most memory
    ** allocators round up memory allocations at least to the next multiple
    ** of 8.  Some allocators round up to a larger multiple or to a power of 2.
    ** Every memory allocation request coming in through [Malloc.sqlite3_malloc()]
    ** or [Malloc.sqlite3_realloc()] first calls xRoundup.  If xRoundup returns 0, 
    ** that causes the corresponding memory allocation to fail.
    **
    ** The xInit method initializes the memory allocator.  (For example,
    ** it might allocate any require mutexes or initialize internal data
    ** structures.  The xShutdown method is invoked (indirectly) by
    ** [sqlite3_shutdown()] and should deallocate any resources acquired
    ** by xInit.  The pAppData pointer is used as the only parameter to
    ** xInit and xShutdown.
    **
    ** SQLite holds the [MutexType.SQLITE_MUTEX_STATIC_MASTER] mutex when it invokes
    ** the xInit method, so the xInit method need not be threadsafe.  The
    ** xShutdown method is only called from [sqlite3_shutdown()] so it does
    ** not need to be threadsafe either.  For all other methods, SQLite
    ** holds the [MutexType.SQLITE_MUTEX_STATIC_MEM] mutex as long as the
    ** [ConfigOption.SQLITE_CONFIG_MEMSTATUS] configuration option is turned on (which
    ** it is by default) and so the methods are automatically serialized.
    ** However, if [ConfigOption.SQLITE_CONFIG_MEMSTATUS] is disabled, then the other
    ** methods must be threadsafe or else make their own arrangements for
    ** serialization.
    **
    ** SQLite will never invoke xInit() more than once without an intervening
    ** call to xShutdown().
    */
    //typedef struct sqlite3_mem_methods sqlite3_mem_methods;
    //struct sqlite3_mem_methods {
    //  void *(*xMalloc)(int);         /* Memory allocation function */
    //  void (*xFree)(void*);          /* Free a prior allocation */
    //  void *(*xRealloc)(void*,int);  /* Resize an allocation */
    //  int (*xSize)(void*);           /* Return the size of an allocation */
    //  int (*xRoundup)(int);          /* Round up request size to allocation size */
    //  int (*xInit)(void*);           /* Initialize the memory allocator */
    //  void (*xShutdown)(void*);      /* Deinitialize the memory allocator */
    //  void *pAppData;                /* Argument to xInit() and xShutdown() */
    //};
    public struct sqlite3_mem_methods
    {
        public object pAppData; /* Argument to xInit() and xShutdown() */
        public dxFree xFree; //void (*xFree)(void*);          /* Free a prior allocation */
        public dxFreeInt xFreeInt; //void (*xFree)(void*);          /* Free a prior allocation */
        public dxFreeMem xFreeMem; //void (*xFree)(void*);          /* Free a prior allocation */
        public dxMemInit xInit; //int (*xInit)(void*);           /* Initialize the memory allocator */
        public dxMalloc xMalloc; //void *(*xMalloc)(int);         /* Memory allocation function */
        public dxMallocInt xMallocInt; //void *(*xMalloc)(int);         /* Memory allocation function */
        public dxMallocMem xMallocMem; //void *(*xMalloc)(int);         /* Memory allocation function */
        public dxRealloc xRealloc; //void *(*xRealloc)(void*,int);  /* Resize an allocation */
        public dxRoundup xRoundup; //int (*xRoundup)(int);          /* Round up request size to allocation size */
        public dxMemShutdown xShutdown; //void (*xShutdown)(void*);      /* Deinitialize the memory allocator */
        public dxSize xSize; //int (*xSize)(void*);           /* Return the size of an allocation */

        public sqlite3_mem_methods(
            dxMalloc xMalloc,
            dxMallocInt xMallocInt,
            dxMallocMem xMallocMem,
            dxFree xFree,
            dxFreeInt xFreeInt,
            dxFreeMem xFreeMem,
            dxRealloc xRealloc,
            dxSize xSize,
            dxRoundup xRoundup,
            dxMemInit xInit,
            dxMemShutdown xShutdown,
            object pAppData
            )
        {
            this.xMalloc = xMalloc;
            this.xMallocInt = xMallocInt;
            this.xMallocMem = xMallocMem;
            this.xFree = xFree;
            this.xFreeInt = xFreeInt;
            this.xFreeMem = xFreeMem;
            this.xRealloc = xRealloc;
            this.xSize = xSize;
            this.xRoundup = xRoundup;
            this.xInit = xInit;
            this.xShutdown = xShutdown;
            this.pAppData = pAppData;
        }
    }
}